package com.sdhs.listmanage.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sdhs.common.exception.ServiceException;
import com.sdhs.common.utils.DateUtils;
import com.sdhs.common.utils.SecurityUtils;
import com.sdhs.common.utils.StringUtils;
import com.sdhs.listmanage.domain.GcManageListTemporary;
import com.sdhs.listmanage.domain.ManageTreeSelect;
import com.sdhs.listmanage.domain.bo.GcProjectManageListBo;
import com.sdhs.listmanage.domain.entity.GcManageList;
import com.sdhs.listmanage.domain.vo.GcProjectManageListVo;
import com.sdhs.listmanage.mapper.GcManageListMapper;
import com.sdhs.listmanage.mapper.GcManageListTemporaryMapper;
import com.sdhs.listmanage.service.IGcManageListService;
import com.sdhs.listmanage.service.IGcProjectManageListService;

import cn.hutool.core.bean.BeanUtil;
import org.springframework.transaction.annotation.Transactional;


/**
 * 清单管理Service业务层处理
 *
 * @author ww
 */
@Service
public class GcManageListServiceImpl implements IGcManageListService {
    @Autowired
    private GcManageListMapper gcManageListMapper;

    @Autowired
    private IGcProjectManageListService gcProjectManageListService;

    @Autowired
    private GcManageListTemporaryMapper gcManageListTemporaryMapper;
    /**
     * 查询清单管理
     *
     * @param id 清单管理主键
     * @return 清单管理
     */
    @Override
    public GcManageList selectGcManageListById(Long id) {
        return gcManageListMapper.selectGcManageListById(id);
    }

    /**
     * 根据项目id查询清单管理
     *
     * @return 清单管理
     */
    @Override
    public List<GcManageList> selectGcManageListByProject(Long projectId) {
        return gcManageListMapper.selectGcManageListByProject(projectId);
    }
    /**
     * 查询清单树结构信息
     *
     * @return 清单树信息集合
     */
    @Override
    public List<ManageTreeSelect> selectManageListTreeList(GcManageList gcManageList)
    {
        List<GcManageList> manageList = selectGcManageListList(gcManageList);
        return buildDeptTreeSelect(manageList);
    }

    /**
     * 查询清单管理列表
     *
     * @return 清单管理
     */
    @Override
    public List<GcManageList> selectGcManageListList(GcManageList gcManageList) {
        return gcManageListMapper.selectGcManageListList(gcManageList);
    }

    /**
     * 新增清单管理
     *
     * @param gcManageList 清单管理
     * @return 结果
     */
    @Override
    public int insertGcManageList(GcManageList gcManageList) {
        gcManageList.setCreater(SecurityUtils.getUsername());
        gcManageList.setCreateTime(DateUtils.getNowDate());
        gcManageList.setIsDelete("0");
        return gcManageListMapper.insertGcManageList(gcManageList);
    }

    /**
     * 修改清单管理
     *
     * @param gcManageList 清单管理
     * @return 结果
     */
    @Override
    public int updateGcManageList(GcManageList gcManageList) {
        /*       //对接营销没登录，获取不到用户名
        gcManageList.setUpdater(SecurityUtils.getUsername());
        gcManageList.setUpdateTime(DateUtils.getNowDate());*/
        return gcManageListMapper.updateGcManageList(gcManageList);
    }

    @Override
    public int updateByBusinessId(GcManageList gcManageList) {
        return gcManageListMapper.updateByBusinessId(gcManageList);
    }
    @Override
    public List<GcManageList> selectGcManageListByBusiness(GcManageList gcManageList) {
        return gcManageListMapper.selectGcManageListByBusiness(gcManageList);
    }
    /**
     * 修改清单管理
     *
     * @return 结果
     */
    @Override
    public int update(GcManageList gcManageList) {
         int i = gcManageListMapper.update(gcManageList.getProjectId());
        /*清单锁定的时候将清单数据同步到清单备份表中*/
        /*获取清单数据*/
        List<GcManageList> gcManageLists = gcManageListMapper.selectGcManageListByProject(gcManageList.getProjectId());
        for (int j = 0; j < gcManageLists.size(); j++) {
            GcManageList gcManageList1 = gcManageLists.get(j);
            GcManageListTemporary manageList = BeanUtil.toBean(gcManageList1, GcManageListTemporary.class);
            gcManageListTemporaryMapper.insertGcManageList(manageList);
        }
        return i;
    }

    /**
     * 清单管理-导入
     *
     * @param manageList 清单管理列表
     * @param importUser 操作用户
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importGcManageList(List<GcManageList> manageList, Long projectId, String importUser) {
        if (StringUtils.isNull(manageList) || manageList.isEmpty()) {
            throw new ServiceException("导入数据不能为空！");
        }

        // 判断项目清单主表是否存在 该项目的清单
        GcProjectManageListVo projectManageListVo = gcProjectManageListService.getInfoByProjectId(projectId);
        if (StringUtils.isNull(projectManageListVo)) {
            //项目清单主表不存在该项目的清单, 则新增项目清单
            GcProjectManageListBo projectManageListBo = new GcProjectManageListBo();
            projectManageListBo.setProjectId(projectId);
            gcProjectManageListService.insertByBo(projectManageListBo);
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        Date nowDate = DateUtils.getNowDate();
        //for循环遍历GcManageList
        for (int i = 0; i < manageList.size(); i++) {
            GcManageList item = manageList.get(i);
            item.setCreater(importUser);
            item.setCreateTime(nowDate);
            item.setProjectId(projectId);
            StringBuilder failureMsgRow = new StringBuilder();
            if (StringUtils.isBlank(item.getSubheadingsName())) {
            	failureMsgRow.append("子目名称不能为空；");
            }
            if (isLeafNode(item)) {
            	manageListValidate(item, failureMsgRow);
                String handleSubheadings = null;
                //判断子目号是否以"_"开头
                if (!StringUtils.startsWith(item.getSubheadingsNumber(), "-")) {
                    //设置父节点（如子节点10_1_1，则父节点设置10_1）
                    handleSubheadings = StringUtils.substringBeforeLast(item.getSubheadingsNumber(), "-");
                }
                List<GcManageList> subList = new ArrayList<>(manageList.subList(0, i));
                Collections.reverse(subList);
                String parentSubheadings = handleParentSubheadings(subList, handleSubheadings);
                if (StringUtils.isBlank(parentSubheadings)) {
                    failureMsgRow.append("无法找到父节点；");
                } 
                if (failureMsgRow.length() == 0) {
                	manageListCompute(item);
                    item.setParentSubheadings(parentSubheadings);
                }
            } else {
                //设置父节点（如父节点10_1_1，则上级父节点设置10_1）
                String handleSubheadings = StringUtils.substringBeforeLast(item.getSubheadingsNumber(), "-");
                List<GcManageList> subList = new ArrayList<>(manageList.subList(0, i));
                Collections.reverse(subList);
                String parentSubheadings = handleParentSubheadings(subList, handleSubheadings);
                if (StringUtils.isNotEmpty(parentSubheadings)) {
                    item.setParentSubheadings(parentSubheadings);
                }
            }
            if (failureMsgRow.length() > 0) {
            	// 当前行校验失败
            	failureNum++;
            	failureMsgRow.insert(0, "<br/>第 " + (i + 3) + " 行：");
            	failureMsg.append(failureMsgRow);
            } else {
            	// 当前行校验成功
            	successNum++;
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据校验失败，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
        	/*根据项目id查询清单管理是否有数据，如果有的话就删除之前的数据*/
            List<GcManageList> gcManageLists = selectGcManageListByProject(projectId);
            if (gcManageLists.size() > 0) {
                deleteGcManageListByProjectId(projectId);
            }
            int batchSize = 500; // 每批插入500条
            for (int i = 0; i < manageList.size(); i += batchSize) {
                List<GcManageList> batchList = manageList.subList(i, Math.min(i + batchSize, manageList.size()));
                gcManageListMapper.insertGcManageListDates(batchList);
            }
            /*gcManageListMapper.insertGcManageListDates(manageList);*/
            successMsg.insert(0, "恭喜您，数据已全部导入成功，共 " + successNum + " 条。");
        }
        return successMsg.toString();
    }
    
    /**
     * 子节点必填校验
     * @param manageList
     * @return
     */
    public void manageListValidate(GcManageList item, StringBuilder failureMsgRow) {
    	if (StringUtils.isBlank(item.getUnit())) {
        	failureMsgRow.append("单位不能为空；");
        }
    	if (StringUtils.isBlank(item.getQuantity())) {
        	failureMsgRow.append("合同数量不能为空；");
        }
    	if (StringUtils.isBlank(item.getSalePrice())) {
        	failureMsgRow.append("含税单价不能为空；");
        }
    	if (StringUtils.isBlank(item.getDevicePrice())) {
        	failureMsgRow.append("设备含税单价不能为空；");
        }
    	if (StringUtils.isBlank(item.getConstructionPrice())) {
        	failureMsgRow.append("施工含税单价不能为空；");
        }
    	if (StringUtils.isBlank(item.getOtherPrice())) {
        	failureMsgRow.append("服务含税单价不能为空；");
        }
    }
    
    /**
     * 清单导入时，计算字段的值
     * @param manageList
     */
    public void manageListCompute(GcManageList manageList) {
    	// 定义常量 100
        BigDecimal hundred = BigDecimal.valueOf(100);
    	// 含税单价
    	String salePrice = manageList.getSalePrice();
    	BigDecimal salePriceBd = new BigDecimal(salePrice);
    	// 合同数量
    	String quantity = manageList.getQuantity();
    	BigDecimal quantityBd = new BigDecimal(quantity);
    	// 税率（%）
    	String rateTax = manageList.getRateTax();
    	if (StringUtils.isBlank(rateTax)) {
    		rateTax = "13";
    		manageList.setRateTax(rateTax);
    	}
    	BigDecimal rateTaxBd = new BigDecimal(rateTax);
    	// 合同含税合价计算
    	BigDecimal saleSumPriceBd = salePriceBd.multiply(quantityBd).setScale(2, RoundingMode.HALF_UP);
    	String saleSumPrice = saleSumPriceBd.toString();
    	manageList.setSaleSumPrice(saleSumPrice);
    	// 不含税单价计算
    	BigDecimal denominator = hundred.add(rateTaxBd);
    	BigDecimal unitPrice = salePriceBd.divide(denominator, 10, RoundingMode.HALF_UP).multiply(hundred).setScale(2, RoundingMode.HALF_UP);
    	manageList.setUnitPrice(unitPrice);
    	// 合同不含税合价计算
    	BigDecimal totalPrice = unitPrice.multiply(quantityBd).setScale(2, RoundingMode.HALF_UP);
    	manageList.setTotalPrice(totalPrice);
    	// 合同总税金计算
    	BigDecimal contractTotalTax = saleSumPriceBd.subtract(totalPrice).setScale(2, RoundingMode.HALF_UP);
    	manageList.setContractTotalTax(contractTotalTax);
    	// 服务含税单价
    	String otherPrice = manageList.getOtherPrice();
    	BigDecimal otherPriceBd = new BigDecimal(otherPrice);
    	// 施工含税单价
    	String constructionPrice = manageList.getConstructionPrice();
    	BigDecimal constructionPriceBd = new BigDecimal(constructionPrice);
    	// 设备含税单价
    	String devicePrice = manageList.getDevicePrice();
    	BigDecimal devicePriceBd = new BigDecimal(devicePrice);
    	// 设备税率（%）
    	String equipmentTax = manageList.getEquipmentTax();
    	if (StringUtils.isBlank(equipmentTax)) {
    		equipmentTax = "13";
    		manageList.setEquipmentTax(equipmentTax);
    	}
    	BigDecimal equipmentTaxBd = new BigDecimal(equipmentTax);
    	// 施工税率（%）
    	String constructionTax = manageList.getConstructionTax();
    	if (StringUtils.isBlank(constructionTax)) {
    		constructionTax = "9";
    		manageList.setConstructionTax(constructionTax);
    	}
    	BigDecimal constructionTaxBd = new BigDecimal(constructionTax);
    	// 服务税率（%）
    	String serviceTax = manageList.getServiceTax(); 
    	if (StringUtils.isBlank(serviceTax)) {
    		serviceTax = "6";
    		manageList.setServiceTax(serviceTax);
    	}
    	BigDecimal serviceTaxBd = new BigDecimal(serviceTax);
    	// 综合含税单价计算
    	BigDecimal bidCostPriceBd = otherPriceBd.add(constructionPriceBd).add(devicePriceBd).setScale(2, RoundingMode.HALF_UP);
    	String bidCostPrice = bidCostPriceBd.toString();
    	manageList.setBidCostPrice(bidCostPrice);
    	// 综合含税合价计算
    	BigDecimal costNegotiableBd = bidCostPriceBd.multiply(quantityBd).setScale(2, RoundingMode.HALF_UP);
    	String costNegotiable = costNegotiableBd.toString();
    	manageList.setCostNegotiable(costNegotiable);
    	// 综合不含税合价计算
    	BigDecimal deviceNet = devicePriceBd.divide(equipmentTaxBd.add(hundred), 10, RoundingMode.HALF_UP).multiply(hundred);
        BigDecimal constructionNet = constructionPriceBd.divide(constructionTaxBd.add(hundred), 10, RoundingMode.HALF_UP).multiply(hundred);
        BigDecimal otherNet = otherPriceBd.divide(serviceTaxBd.add(hundred), 10, RoundingMode.HALF_UP).multiply(hundred);
    	BigDecimal comprehensivePrice = deviceNet.add(constructionNet).add(otherNet).multiply(quantityBd).setScale(2, RoundingMode.HALF_UP);
    	manageList.setComprehensivePrice(comprehensivePrice);
    	// 标前测算总税金计算
    	BigDecimal preTotalTax = costNegotiableBd.subtract(comprehensivePrice).setScale(2, RoundingMode.HALF_UP);
    	manageList.setPreTotalTax(preTotalTax);
    }

    /**
     * 批量删除清单管理
     *
     * @param ids 需要删除的清单管理主键
     * @return 结果
     */
    @Override
    public int deleteGcManageListByIds(Long[] ids) {
        return gcManageListMapper.deleteGcManageListByIds(ids);
    }

    /**
     * 删除清单管理信息
     *
     * @param id 清单管理主键
     * @return 结果
     */
    @Override
    public int deleteGcManageListById(Long id) {
        return gcManageListMapper.deleteGcManageListById(id);
    }
    /**
     * 根据项目id删除清单信息
     * */
    @Override
    public int deleteGcManageListByProjectId(Long projectId) {
        return gcManageListMapper.deleteGcManageListByProjectId(projectId);
    }

    /**
     * 获取父节点-子目号
     *
     * @param manageList 清单管理列表
     * @return 结果
     */
    public String handleParentSubheadings(List<GcManageList> manageList, String parentSubheadings) {
        return manageList.stream()
                .filter(this::isParentNode)
                .filter(item -> isSubheadingMatch(item, parentSubheadings))
                .findFirst()
                .map(GcManageList::getSubheadingsNumber)
                .orElse("");
    }

    /**
     * 判断清单管理-子目号是否匹配
     *
     * @param item 清单管理对象
     * @param parentSubheadings 父节点-子目号
     * @return 结果
     */
    private boolean isSubheadingMatch(GcManageList item, String parentSubheadings) {
        return item.getSubheadingsNumber() == null
                || parentSubheadings == null
                || parentSubheadings.isEmpty()
                || Objects.equals(item.getSubheadingsNumber(), parentSubheadings);
    }

    /**
     * 判断清单管理-是否是父节点
     *
     * @param item 清单管理对象
     * @return 结果
     */
    @Override
    public boolean isLeafNode(GcManageList item) {
    	return !isParentNode(item);
    }

    /**
     * 判断清单管理-是否父节点
     *
     * @param item 清单管理对象
     * @return 结果
     */
    public boolean isParentNode(GcManageList item) {
    	return StringUtils.isBlank(item.getUnit())
    			&& StringUtils.isBlank(item.getQuantity())
    			&& StringUtils.isBlank(item.getSalePrice())
    			&& StringUtils.isBlank(item.getDevicePrice())
    			&& StringUtils.isBlank(item.getConstructionPrice())
    			&& StringUtils.isBlank(item.getOtherPrice());
    }


    /**
     * 构建前端所需要下拉树结构
     *
     * @param manageList 清单列表
     * @return 下拉树结构列表
     */
    @Override
    public List<ManageTreeSelect> buildDeptTreeSelect(List<GcManageList> manageList)
    {
        List<GcManageList> deptTrees = buildManageListTree(manageList);
        return deptTrees.stream().map(ManageTreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 构建前端所需要树结构
     *
     * @param manageList 清单列表
     * @return 树结构列表
     */
    public List<GcManageList> buildManageListTree(List<GcManageList> manageList)
    {
        List<GcManageList> returnList = new ArrayList<>();
        List<String> tempList = manageList.stream().map(GcManageList::getSubheadingsNumber).collect(Collectors.toList());
        for (GcManageList item : manageList)
        {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(item.getParentSubheadings()))
            {
                recursionFn(manageList, item);
                returnList.add(item);
            }
        }
        if (returnList.isEmpty()) {
            returnList = manageList;
        }
        return returnList;
    }
    /**
     * 递归列表
     */
    private void recursionFn(List<GcManageList> list, GcManageList t)
    {
        // 得到子节点列表
        List<GcManageList> childList = getChildList(list, t);
        t.setChildren(childList);
        for (GcManageList tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<GcManageList> getChildList(List<GcManageList> list, GcManageList t)
    {
        List<GcManageList> tlist = new ArrayList<>();
        for (GcManageList n : list) {
            if (StringUtils.isNotEmpty(n.getParentSubheadings())
                    && n.getParentSubheadings().equals(t.getSubheadingsNumber())) {
                tlist.add(n);
            }
        }
        return tlist;
    }


    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<GcManageList> list, GcManageList t)
    {
        return !getChildList(list, t).isEmpty();
    }


}
